'''
Author: Deven
Email: liming@tuya.com
LastEditors: Please set LastEditors
FileName: &file name&
Description: 
Copyright: HANGZHOU TUYA INFORMATION TECHNOLOGY CO.,LTD
Company: http://www.tuya.com
Date: 2021-10-22 14:53:35
LastEditTime: 2021-12-26 17:28:08
'''
#encoding='utf-8'
import os
import sys
import json
import collections
import shutil
import tarfile
import time
import threading

#*****************************************************************#
# NOTE: This script is a compiled script. Please do not modify it #
#*****************************************************************#
# Post Build processing.

SOURCE_PTAH = sys.argv[1]
SOURCE_PTAH = SOURCE_PTAH.replace('\\','/') 
SOURCE_NAME = os.path.basename(SOURCE_PTAH)
APP_NAME = sys.argv[2]
PROJECT_VERSION = sys.argv[3]

PROJECT_PATH = '../../'+SOURCE_PTAH
PROJECT_BUILD_PATH = PROJECT_PATH+'/_build'
PROJECT_OUTPUT_PATH = PROJECT_PATH+'/output'

POST_BUILD_PATH = os.getcwd()+'/tools/templates'
MACRO_JSON_CONFIG_PATH = './macro_config.json'

PARAMETER_LINE1="-@echo 'Building file: $<'"
PARAMETER_LINE2="-@echo 'Invoking: TC32 Compiler'"
PARAMETER_LINE4="-@echo 'Finished building: $<'"
PARAMETER_LINE5="-@echo ' '"
MK_PARAMETER_HEAD='../../../tools/tc32/tc32/bin/tc32-elf-gcc -ffunction-sections -fdata-sections '
MK_PARAMETER_TAIL=' -Wall -O2 -fshort-enums -finline-small-functions -std=gnu99 -fshort-wchar -fms-extensions -c -o"$@" "$<"'

SOURCE_PATHS = []
SOURCE_VALUE = ''
MACRO_VALUE = ''

def alter(file,old_str,new_str):
    if not os.path.isfile(file):
        return False
    file_data = ""
    with open(file, "r", encoding="utf-8") as f:
        for line in f:
            if old_str in line:
                line = line.replace(old_str,new_str)
            file_data += line
    with open(file,"w",encoding="utf-8") as f:
        f.write(file_data)  


def addappMk(file,source_file,target_file,total_source,define_macro):
    if not os.path.isfile(file):
        return False
    with open(file,'a') as f:
        f.writelines('\n'+'\n'+target_file + ': ' + source_file)
        f.writelines('\n'"	"+ PARAMETER_LINE1)
        f.writelines('\n'"	"+ PARAMETER_LINE2)
        f.writelines('\n'"	"+ MK_PARAMETER_HEAD + total_source + define_macro + MK_PARAMETER_TAIL)
        f.writelines('\n'"	"+ PARAMETER_LINE4)
        f.writelines('\n'"	"+ PARAMETER_LINE5)


def get_source_path(sourcePath,target_buf):
    if not os.path.isdir(sourcePath):
        return False
    listName = os.listdir(sourcePath)
    for name in listName:
        sourceAbs = os.path.join(sourcePath, name)
        sourceAbs = sourceAbs.replace('\\','/')
        if os.path.isdir(sourceAbs):
            listName = os.listdir(sourceAbs)
            for name in listName:
                if (os.path.splitext(name)[1] == '.h' or os.path.splitext(name)[1] == '.s' or os.path.splitext(name)[1] == '.a'):
                    if not sourcePath in target_buf:
                        target_buf.append('\"../'+sourceAbs+'\"')
                    break 
            get_source_path(sourceAbs,target_buf)

def get_target_path(target_Path):
    listName = os.listdir(target_Path)
    for name in listName:
        if (os.path.splitext(name)[1] == '.h' or os.path.splitext(name)[1] == '.s' or os.path.splitext(name)[1] == '.a'):
            SOURCE_PATHS.append('\"../'+target_Path+'\"')
            break 

    get_source_path(target_Path,SOURCE_PATHS)


def generate_mk_file(sourcePath,target_mk):
    if not os.path.isdir(sourcePath):
        return False
    listName = os.listdir(sourcePath)
    for name in listName:
        if(name == 'os'):
            continue
        sourceAbs = os.path.join(sourcePath, name)
        sourceAbs = sourceAbs.replace('\\','/')
        if os.path.splitext(name)[1] == '.c':
            filename = os.path.join(sourcePath, os.path.splitext(name)[0])
            filename = filename.replace('\\','/') 
            alter(target_mk,'C_SRCS += \\','C_SRCS += \\'+'\n'+filename+'.c'+' \\')
            targetAbs = filename.replace('../','')
            alter(target_mk,'OBJS += \\','OBJS += \\'+'\n'+targetAbs+'.o'+' \\')
            addappMk(target_mk,filename+'.c',targetAbs+'.o',SOURCE_VALUE,MACRO_VALUE)
        if os.path.splitext(name)[1] == '.S':
            filename = os.path.join(sourcePath, os.path.splitext(name)[0])
            filename = filename.replace('\\','/') 
            alter(target_mk,'C_SRCS += \\','C_SRCS += \\'+'\n'+filename+'.S'+' \\')
            targetAbs = filename.replace('../','')
            alter(target_mk,'OBJS += \\','OBJS += \\'+'\n'+targetAbs+'.o'+' \\')
            addappMk(target_mk,filename+'.s',targetAbs+'.o',SOURCE_VALUE,MACRO_VALUE)
        if os.path.isdir(sourceAbs):
            generate_mk_file(sourceAbs,target_mk) 


def copyDir(sourcePath, targetPath):
    if not os.path.isdir(sourcePath):
        return False
    if not os.path.exists(targetPath):
        os.makedirs(targetPath)
    sourceStack = collections.deque()
    sourceStack.append(sourcePath)
    targetStack = collections.deque()
    targetStack.append(targetPath)
    while True:
        if len(sourceStack) == 0:
            break
        sourcePath = sourceStack.pop()  # sourcePath = sourceStack.popleft()
        listName = os.listdir(sourcePath)

        targetPath = targetStack.pop()  # targetPath = targetStack.popleft()
        if not os.path.isdir(targetPath):
            os.makedirs(targetPath)
        for name in listName:
            if (sourcePath == PROJECT_PATH and (name == '_build' or name == 'output')):
                continue
            sourceAbs = os.path.join(sourcePath, name)
            targetAbs = os.path.join(targetPath, name)
            if os.path.isdir(sourceAbs):
                if not os.path.exists(targetAbs):
                    os.makedirs(targetAbs)
                sourceStack.append(sourceAbs)
                targetStack.append(targetAbs)


# firmware info parser
def app_firmware_info_collect(DEVICE_TYPE):
    # global PROJECT_NAME
    # global SOURCE_NAME
    # global SOURCE_PATHS
    global MACRO_SYMBLOS
    # print("firmware information parse start...")
    file = open(MACRO_JSON_CONFIG_PATH, 'rb')
    fileJson = json.load(file, object_pairs_hook=collections.OrderedDict)
    # PROJECT_NAME = fileJson['app']['project_name']
    # SOURCE_NAME = fileJson['app']['source_name']
    # SOURCE_PATHS = fileJson['app']['source_paths']
    if DEVICE_TYPE=='router':
        MACRO_SYMBLOS = fileJson['router']['macro_symblos']
    elif DEVICE_TYPE=='sleep_end_dev':
        MACRO_SYMBLOS = fileJson['sleep_end_dev']['macro_symblos']
    file.close()
    # print("firmware information parse success")
    # print(PROJECT_NAME)
    # print(SOURCE_PATHS)
    # print(MACRO_SYMBLOS)

def copy_demo_file(source,target):
    source_path = os.path.abspath(r''+source)
    target_path = os.path.abspath(r''+target)

    if not os.path.exists(target_path):
        os.makedirs(target_path)

    if os.path.exists(source_path):
        shutil.rmtree(target_path)
        shutil.copytree(source_path, target_path)

def deldir(dir):
    if not os.path.exists(dir):
        return False
    if os.path.isfile(dir):
        os.remove(dir)
        return
    for i in os.listdir(dir):
        t = os.path.join(dir, i)
        if os.path.isdir(t):
            deldir(t)#重新调用次方法
        else:
            os.unlink(t)
    os.rmdir(dir)#递归删除目录下面的空文件夹

def deloutputfile(dir):
    if not os.path.exists(dir):
        return False
    for i in os.listdir(dir):
        t = os.path.join(dir, i)
        if os.path.isdir(t):
            deloutputfile(t)
        else:
            if os.path.splitext(i)[1] == '.o':
                file_path=t.replace('\\','/')
                file_path=file_path.replace('../','')
                print(file_path)
                os.remove(t)

def make():
    print(os.getcwd())
    global waitting_make_over
    if not os.path.isfile('build.log'):
        f=open('build.log','w') # r只读，w可写，a追加
        f.close()
    waitting_make_over = 1
    os.system('make all >build.log 2>&1' )
    waitting_make_over = 0

class Post_build(object):
    def __init__(self,DEVICE_TYPE,BUILD_COMMAND):
        global SOURCE_VALUE
        global MACRO_VALUE

        if (BUILD_COMMAND == 'build'):

            os.chdir(POST_BUILD_PATH)

            source = ''
            macro = ''

            if not os.path.exists(PROJECT_BUILD_PATH):
                os.makedirs(PROJECT_BUILD_PATH)
            
            if not os.path.exists(PROJECT_OUTPUT_PATH):
                os.makedirs(PROJECT_OUTPUT_PATH)

            if not os.path.exists(PROJECT_BUILD_PATH+'/'+SOURCE_NAME):
                copyDir(PROJECT_PATH,PROJECT_BUILD_PATH+'/'+SOURCE_NAME)

            if not os.path.exists(PROJECT_BUILD_PATH+'/components'):
                copyDir('../../components',PROJECT_BUILD_PATH+'/components')

            if not os.path.exists(PROJECT_BUILD_PATH+'/include'):
                copyDir('../../include',PROJECT_BUILD_PATH+'/include')

            if not os.path.exists(PROJECT_BUILD_PATH+'/libs'):
                copyDir('../../libs',PROJECT_BUILD_PATH+'/libs')

            if not os.path.exists(PROJECT_BUILD_PATH+'/vendor'):
                copyDir('../../vendor',PROJECT_BUILD_PATH+'/vendor')

            copy_demo_file('./makefile_demo','./temp')

            app_firmware_info_collect(DEVICE_TYPE)

            search_paths = [PROJECT_PATH, '../../include', '../../libs', '../../vendor','../../components']

            for i in search_paths:
                get_target_path(i)

            for i in SOURCE_PATHS:
                source = source + ' -I'+ i

            for i in MACRO_SYMBLOS:
                macro = macro + ' -D'+ i

            SOURCE_VALUE = source
            MACRO_VALUE = macro

            os.chdir(PROJECT_BUILD_PATH)
            generate_mk_file('../../../components',POST_BUILD_PATH+'/temp/components.mk')
            generate_mk_file('../../../include',POST_BUILD_PATH+'/temp/include.mk')
            generate_mk_file('../../../libs',POST_BUILD_PATH+'/temp/libs.mk')
            generate_mk_file('../../../vendor',POST_BUILD_PATH+'/temp/vendor.mk')
            generate_mk_file('../../'+SOURCE_NAME,POST_BUILD_PATH+'/temp/app.mk')
            os.chdir(POST_BUILD_PATH)

            alter(POST_BUILD_PATH+'/temp/makefile','__TuyaOS_Project_Source',SOURCE_NAME)
            alter(POST_BUILD_PATH+'/temp/makefile','__TuyaOS_Project_Name',APP_NAME)
            alter(POST_BUILD_PATH+'/temp/makefile','__TuyaOS_Project_Version',PROJECT_VERSION)

            if DEVICE_TYPE=='router':
                alter(POST_BUILD_PATH+'/temp/objects.mk','__Tuyaos_telink_tal_target_name','_router_tal_telink_zigbee_release')
                alter(POST_BUILD_PATH+'/temp/objects.mk','__Tuyaos_telink_tkl_target_name','_router_tkl_telink_zigbee_release')
                alter(POST_BUILD_PATH+'/temp/objects.mk','__Tuyaos_telink_sdk_lib_target_name','zb_router')
                alter(POST_BUILD_PATH+'/temp/makefile','-L../../../libs/tuya_lib','-L../../../libs/tuya_lib/router')
            elif DEVICE_TYPE=='sleep_end_dev':
                alter(POST_BUILD_PATH+'/temp/objects.mk','__Tuyaos_telink_tal_target_name','_ed_tal_telink_zigbee_release')
                alter(POST_BUILD_PATH+'/temp/objects.mk','__Tuyaos_telink_tkl_target_name','_ed_tkl_telink_zigbee_release')
                alter(POST_BUILD_PATH+'/temp/objects.mk','__Tuyaos_telink_sdk_lib_target_name','zb_ed')
                alter(POST_BUILD_PATH+'/temp/makefile','-L../../../libs/tuya_lib','-L../../../libs/tuya_lib/sleep_device')
            
            deldir(PROJECT_BUILD_PATH+'/'+'components.mk')
            deldir(PROJECT_BUILD_PATH+'/'+'include.mk')
            deldir(PROJECT_BUILD_PATH+'/'+'libs.mk')
            deldir(PROJECT_BUILD_PATH+'/'+'vendor.mk') 
            deldir(PROJECT_BUILD_PATH+'/'+'app.mk')
            deldir(PROJECT_BUILD_PATH+'/'+'objects.mk')
            deldir(PROJECT_BUILD_PATH+'/'+'sources.mk')
            deldir(PROJECT_BUILD_PATH+'/'+'makefile')
            shutil.copyfile(POST_BUILD_PATH+'/temp/components.mk',PROJECT_BUILD_PATH+'/'+'components.mk')
            shutil.copyfile(POST_BUILD_PATH+'/temp/include.mk',PROJECT_BUILD_PATH+'/'+'include.mk')
            shutil.copyfile(POST_BUILD_PATH+'/temp/libs.mk',PROJECT_BUILD_PATH+'/'+'libs.mk')
            shutil.copyfile(POST_BUILD_PATH+'/temp/vendor.mk',PROJECT_BUILD_PATH+'/'+'vendor.mk')
            shutil.copyfile(POST_BUILD_PATH+'/temp/app.mk',PROJECT_BUILD_PATH+'/'+'app.mk')
            shutil.copyfile(POST_BUILD_PATH+'/temp/objects.mk',PROJECT_BUILD_PATH+'/'+'objects.mk')
            shutil.copyfile(POST_BUILD_PATH+'/temp/sources.mk',PROJECT_BUILD_PATH+'/'+'sources.mk')
            shutil.copyfile(POST_BUILD_PATH+'/temp/makefile',PROJECT_BUILD_PATH+'/'+'makefile')

            if not os.path.exists('../tc32/tc32/bin'):
                os.chdir('../tc32')
                filename = 'tc32_win.tar.gz'
                print('uncompressing tc32_win.tar.gz ... ')
                tf = tarfile.open(filename)
                tf.extractall('../tc32')
                os.chdir(POST_BUILD_PATH)

            for name in os.listdir('../tc32/tc32/bin'):
                if name == 'make.exe' or os.path.splitext(name)[1] == '.dll':
                    if not os.path.exists(PROJECT_BUILD_PATH+'/'+ name):
                        sourceAbs = os.path.join('../tc32/tc32/bin', name)
                        sourceAbs = sourceAbs.replace('\\','/')
                        shutil.copyfile(sourceAbs,PROJECT_BUILD_PATH+'/'+ name)

            # # 1-cmake 构建编译系统
            deldir('./temp')
            if os.path.exists(PROJECT_BUILD_PATH):
                os.chdir(PROJECT_BUILD_PATH)
                deldir('./build.log')

                thread = threading.Thread(target=make)
                thread.start()
                time.sleep(0.1)

                with open('build.log','r') as f:
                    while waitting_make_over == 1:
                            line = f.readline()
                            if line:
                                sys.stdout.write(str(line))
                                #print(line)
                            else:
                                time.sleep(0.1)
                    while True:
                        line = f.readline()
                        if line:
                            sys.stdout.write(str(line))
                            #print(line)
                        else:
                            break
                    f.close()
            
                # python_path = 'make '
                # para = "%s \"%s \""%(python_path, 'all')
                # ret = subprocess.call(para)
                # if ret != 0:
                #     print("make execution failed !!!")
                #     sys.exit(1)
                    
                os.chdir(POST_BUILD_PATH)

            os.chdir(os.getcwd())

        elif (BUILD_COMMAND == 'clean'):
            
            os.chdir(POST_BUILD_PATH)
            deldir('./temp')
            print('\nclean start ...\n')
            if os.path.exists(PROJECT_BUILD_PATH):
                deldir(PROJECT_BUILD_PATH)
            print('\nclean end')
            os.chdir(os.getcwd())

        




    
